# -*- coding: utf-8 -*-
import copy
import openpyxl
from common.utils.common_functions import exit_program

"""
    用例数据设计
    测试用例
    test_case:
        [项目模块, 子功能, 功能点, 用例标题, 用例描述, 用例等级, 用例链接地址, 缺陷链接地址, 链接地址, 附件, 标记, [预置条件],
        [[操作步骤, 关键字, 测试数据1， 测试数据2], [操作步骤, 关键字, 测试数据1， 测试数据2], ...]]
        
        
    预置步骤
    self.preset_steps:
        {"用例标题": [[操作步骤, 关键字, 测试数据1， 测试数据2], [操作步骤, 关键字, 测试数据1， 测试数据2],
                    [操作步骤, 关键字, 测试数据1， 测试数据2], [操作步骤, 关键字, 测试数据1， 测试数据2]]}
"""


class ExcelRead:
    _instance = None

    def __new__(cls):
        if cls._instance is None:
            # 创建新的实例
            instance = super().__new__(cls)
            cls._instance = instance
        return cls._instance

    def __init__(self):
        # 判断实例是否已经初始化
        if not hasattr(self, 'authorization_time'):
            # print("ExcelRead::__init__")
            self.test_case_path = "testdata/data_files/test_case.xlsx"

            # epic描述
            self.col_epic_pos = -1
            self.col_epic_text = "项目模块"
            # 用户故事
            self.col_story_pos = -1
            self.col_story_text = "子功能"
            # 模块名称
            self.col_feature_pos = -1
            self.col_feature_text = "功能点"
            # 用例标题
            self.col_title_pos = -1
            self.col_title_text = "用例标题"
            # 用例描述
            self.col_description_pos = -1
            self.col_description_text = "用例描述"
            # 用例等级
            self.col_severity_pos = -1
            self.col_severity_text = "用例等级"
            # 用例链接地址
            self.col_testcase_pos = -1
            self.col_testcase_text = "用例链接地址"
            # 缺陷链接地址
            self.col_issue_pos = -1
            self.col_issue_text = "缺陷链接地址"
            # 定义一个链接，在测试报告展现
            self.col_link_pos = -1
            self.col_link_text = "链接地址"
            # 报告添加附件
            self.col_attachment_pos = -1
            self.col_attachment_text = "附件"
            # 标记
            self.col_markers_pos = -1
            self.col_markers_text = "标记"
            # 预置条件
            self.col_preset_condition_pos = -1
            self.col_preset_condition_text = "预置步骤"
            # 操作步骤
            self.col_step_pos = -1
            self.col_step_text = "操作步骤"
            # 关键字
            self.col_key_word_pos = -1
            self.col_key_word_text = "关键字"
            # 测试数据
            self.col_test_data_pos = -1
            self.col_test_data_text = "测试数据"

            # 几列测试数据
            self.test_data_number = 5
            self.test_use_cases = None
            self.preset_steps = None

            self.workbook = openpyxl.load_workbook(self.test_case_path)
            self.sheet1 = self.workbook.worksheets[0]
            self.sheet2 = self.workbook.worksheets[1]

    # 获取测试报告标题
    def get_report_title(self):
        return self.workbook.sheetnames[0]

    # 定位存在的用例元素位置
    def _use_case_elements_pos(self):
        required_elements_present = True
        column_titles = [cell.value for cell in self.sheet1[1]]
        if self.col_epic_text in column_titles:
            self.col_epic_pos = column_titles.index(self.col_epic_text)
        if self.col_story_text in column_titles:
            self.col_story_pos = column_titles.index(self.col_story_text)
        if self.col_feature_text in column_titles:
            self.col_feature_pos = column_titles.index(self.col_feature_text)
        if self.col_title_text in column_titles:
            self.col_title_pos = column_titles.index(self.col_title_text)
        else:
            print(f"testdata/data_files/test_case*.xlsx，缺少{self.col_title_text}用例元素")
            required_elements_present = False
        if self.col_description_text in column_titles:
            self.col_description_pos = column_titles.index(self.col_description_text)
        if self.col_severity_text in column_titles:
            self.col_severity_pos = column_titles.index(self.col_severity_text)
        if self.col_testcase_text in column_titles:
            self.col_testcase_pos = column_titles.index(self.col_testcase_text)
        if self.col_issue_text in column_titles:
            self.col_issue_pos = column_titles.index(self.col_issue_text)
        if self.col_link_text in column_titles:
            self.col_link_pos = column_titles.index(self.col_link_text)
        if self.col_attachment_text in column_titles:
            self.col_attachment_pos = column_titles.index(self.col_attachment_text)
        if self.col_markers_text in column_titles:
            self.col_markers_pos = column_titles.index(self.col_markers_text)
        if self.col_preset_condition_text in column_titles:
            self.col_preset_condition_pos = column_titles.index(self.col_preset_condition_text)
        if self.col_step_text in column_titles:
            self.col_step_pos = column_titles.index(self.col_step_text)
        else:
            print(f"testdata/data_files/test_case*.xlsx，缺少{self.col_step_text}用例元素")
            required_elements_present = False
        if self.col_key_word_text in column_titles:
            self.col_key_word_pos = column_titles.index(self.col_key_word_text)
        else:
            print(f"testdata/data_files/test_case*.xlsx，缺少{self.col_key_word_text}用例元素")
            required_elements_present = False
        if self.col_test_data_text in column_titles:
            self.col_test_data_pos = column_titles.index(self.col_test_data_text)
        else:
            print(f"testdata/data_files/test_case*.xlsx，缺少{self.col_test_data_text}用例元素")
            required_elements_present = False
        if not required_elements_present:
            exit_program("")

    def get_sheet1_cell_value(self, row, col):
        if col != -1:
            cell_value = self.sheet1.cell(row, col + 1).value
            if cell_value is not None and cell_value.strip():
                return cell_value
        return ""

    # 获取基础用例
    def _get_sheet1_read_data(self):
        test_use_case = []
        if self.col_preset_condition_pos != -1:
            for i in range(self.col_preset_condition_pos):
                test_use_case.append("")
            test_use_case.append([])
            for i in range(self.col_preset_condition_pos + 1, self.col_step_pos):
                test_use_case.append("")
            test_use_case.append([])
        else:
            for i in range(self.col_step_pos):
                test_use_case.append("")
            test_use_case.append([])

        test_use_cases = []
        is_use_case = False
        for row in range(2, self.sheet1.max_row + 1):
            epic_text = self.get_sheet1_cell_value(row, self.col_epic_pos)
            if epic_text:
                if is_use_case:
                    test_use_cases.append(copy.deepcopy(test_use_case))
                    test_use_case[self.col_step_pos] = []
                    if self.col_preset_condition_pos != -1:
                        test_use_case[self.col_preset_condition_pos] = []
                    is_use_case = False
                test_use_case[self.col_epic_pos] = epic_text
                continue
            story_text = self.get_sheet1_cell_value(row, self.col_story_pos)
            if story_text:
                if is_use_case:
                    test_use_cases.append(copy.deepcopy(test_use_case))
                    test_use_case[self.col_step_pos] = []
                    if self.col_preset_condition_pos != -1:
                        test_use_case[self.col_preset_condition_pos] = []
                    is_use_case = False
                test_use_case[self.col_story_pos] = story_text
                continue
            feature_text = self.get_sheet1_cell_value(row, self.col_feature_pos)
            if feature_text:
                if is_use_case:
                    test_use_cases.append(copy.deepcopy(test_use_case))
                    test_use_case[self.col_step_pos] = []
                    if self.col_preset_condition_pos != -1:
                        test_use_case[self.col_preset_condition_pos] = []
                    is_use_case = False
                test_use_case[self.col_feature_pos] = feature_text
                continue

            title_text = self.get_sheet1_cell_value(row, self.col_title_pos)
            if title_text:
                if is_use_case:
                    test_use_cases.append(copy.deepcopy(test_use_case))
                    test_use_case[self.col_step_pos] = []
                    if self.col_preset_condition_pos != -1:
                        test_use_case[self.col_preset_condition_pos] = []
                    is_use_case = False
                test_use_case[self.col_title_pos] = title_text

                test_use_case[self.col_description_pos] = \
                    self.get_sheet1_cell_value(row, self.col_description_pos)

                test_use_case[self.col_severity_pos] = self.get_sheet1_cell_value(row, self.col_severity_pos)

                test_use_case[self.col_testcase_pos] = self.get_sheet1_cell_value(row, self.col_testcase_pos)

                test_use_case[self.col_issue_pos] = self.get_sheet1_cell_value(row, self.col_issue_pos)

                test_use_case[self.col_link_pos] = self.get_sheet1_cell_value(row, self.col_link_pos)

                test_use_case[self.col_attachment_pos] = \
                    self.get_sheet1_cell_value(row, self.col_attachment_pos)

                test_use_case[self.col_markers_pos] = \
                    self.get_sheet1_cell_value(row, self.col_markers_pos)

                preset_condition_text = self.get_sheet1_cell_value(row, self.col_preset_condition_pos)
                if preset_condition_text:
                    test_use_case[self.col_preset_condition_pos].append(preset_condition_text)
                is_use_case = True
                continue

            key_word_text = self.get_sheet1_cell_value(row, self.col_key_word_pos)
            if key_word_text:
                use_case_step = []
                step_text = self.get_sheet1_cell_value(row, self.col_step_pos)
                use_case_step.append(step_text)

                use_case_step.append(key_word_text)

                for test_data_index in range(self.test_data_number):
                    test_data_text = self.get_sheet1_cell_value(row, self.col_test_data_pos + test_data_index)
                    use_case_step.append(test_data_text)

                test_use_case[self.col_step_pos].append(use_case_step)
                continue

        if is_use_case:
            test_use_cases.append(copy.deepcopy(test_use_case))
        # print("\n*****************************************************************\n")
        # for test_use_case in test_use_cases:
        #     print(test_use_case)
        # print("\n*****************************************************************\n")
        self.test_use_cases = test_use_cases

    # 用例参数化
    def _get_sheet2_read_data(self):
        test_use_cases = self.test_use_cases
        new_test_use_cases = []
        sheet2_row_titles = [self.sheet2.cell(row, 1).value for row in range(1, self.sheet2.max_row)]
        # print(sheet2_row_titles)
        for test_use_case_index in range(len(test_use_cases)):
            test_use_case = test_use_cases[test_use_case_index]

            test_use_case_title = test_use_case[self.col_title_pos]
            if test_use_case_title.startswith("@") and test_use_case_title[1:]:
                if test_use_case_title[1:] in sheet2_row_titles:
                    try:
                        new_test_use_case = copy.deepcopy(test_use_case)
                        sheet2_title_pos = sheet2_row_titles.index(test_use_case_title[1:])
                        for sheet2_column in range(1, self.sheet2.max_column):
                            title = self.sheet2.cell(sheet2_title_pos + 1, sheet2_column + 1).value
                            if title is None:
                                break
                            elif title.strip():
                                for element_index in range(len(new_test_use_case)):
                                    if element_index == self.col_preset_condition_pos:
                                        pass
                                    elif element_index == self.col_step_pos:
                                        steps = test_use_case[self.col_step_pos]
                                        for x in range(len(steps[0])):
                                            for y in range(len(steps)):
                                                value = steps[y][x]
                                                if value.startswith("@") and value.strip() != "@":
                                                    if value[1:] in sheet2_row_titles:
                                                        value_row = sheet2_row_titles.index(value[1:])
                                                        new_test_use_case[element_index][y][x] = \
                                                            self.sheet2.cell(value_row + 1, sheet2_column + 1).value
                                                    else:
                                                        exit_program(f"{value}不在用例参数表中")
                                    else:
                                        value = test_use_case[element_index]
                                        if value.startswith("@") and value.strip() != "@":
                                            if value[1:] in sheet2_row_titles:
                                                value_row = sheet2_row_titles.index(value[1:])
                                                new_test_use_case[element_index] = \
                                                    self.sheet2.cell(value_row + 1, sheet2_column + 1).value
                                            else:
                                                exit_program(f"{value}不在用例参数表中")

                                new_test_use_cases.append(copy.deepcopy(new_test_use_case))
                    except ValueError as e:
                        print(e)

                else:
                    exit_program(f"{test_use_case_title}不在用例参数表中")

            else:
                new_test_use_cases.append(copy.deepcopy(test_use_case))

        self.test_use_cases = new_test_use_cases
        # print("\n*****************************************************************\n")
        # for test_use_case in self.test_use_cases:
        #     print(test_use_case)
        # print("\n*****************************************************************\n")

    # 获取预置步骤
    def _get_preset_condition(self):
        test_use_cases = self.test_use_cases
        preset_conditions = []
        titles = []
        for test_use_case in test_use_cases:
            if test_use_case[self.col_preset_condition_pos]:
                preset_condition = test_use_case[self.col_preset_condition_pos][0]
                if preset_condition is not None and preset_condition:
                    preset_conditions.append(preset_condition)
            title = test_use_case[self.col_title_pos]
            if title is not None and title:
                titles.append(title)
        # print(titles)
        # 使用集合去重
        unique_preset_conditions = list(set(preset_conditions))
        # print(unique_preset_conditions)
        # 检查 preset_conditions 中的元素在 titles 中是否重复出现
        is_title_unique = True
        for preset_condition in unique_preset_conditions:
            count_in_titles = titles.count(preset_condition)
            if count_in_titles == 0:
                print(f"预置条件<{preset_condition}>缺失，"
                      f"请确认用例标题为<{preset_condition}>的测试用例是否存在")
                is_title_unique = False
            elif count_in_titles > 1:
                print(f"预置条件<{preset_condition}>重复了，预置条件的标题要唯一，"
                      f"请确认测试用例标题<{preset_condition}>是否多个测试用例使用了")
                is_title_unique = False
        if not is_title_unique:
            exit_program(f"请确认测试用例标题是否存在或者多个测试用例使用了")

        # 存储预置步骤
        self.preset_steps = {}
        for preset_condition in unique_preset_conditions:
            test_use_case_index = titles.index(preset_condition)
            self.preset_steps[preset_condition] = test_use_cases[test_use_case_index][self.col_step_pos]

        # 添加预置步骤
        for index in range(len(test_use_cases)):
            test_use_case = test_use_cases[index]

            if test_use_case[self.col_preset_condition_pos]:
                preset_condition = test_use_case[self.col_preset_condition_pos]
                if preset_condition:
                    if preset_condition[0] == test_use_case[self.col_title_pos]:
                        exit_program(f"{preset_condition[0]}：用例标题与预置步骤冲突"
                                     f"请确保用例标题与预置步骤为不同标题")
                    while True:
                        if preset_condition[0] in titles:
                            test_use_case_index = titles.index(preset_condition[0])
                            preset_condition = test_use_cases[test_use_case_index][self.col_preset_condition_pos]
                            if preset_condition:
                                if preset_condition[0] in self.test_use_cases[index][self.col_preset_condition_pos]:
                                    exit_program(f"请确认测试用例<{test_use_case[self.col_title_pos]}>的"
                                                 f"<{preset_condition[0]}>的预置步骤是否循环添加")
                                self.test_use_cases[index][self.col_preset_condition_pos].insert(0, preset_condition[0])
                            else:
                                break
                        else:
                            exit_program(f"请确认用例标题为<{preset_condition[0]}>的测试用例是否存在")

        print("\n*****************************************************************\n")
        for test_use_case in self.test_use_cases:
            print(test_use_case)
        for key in self.preset_steps:
            print(key, self.preset_steps[key])
        print("\n*****************************************************************\n")

    def get_test_use_cases(self):
        self._use_case_elements_pos()
        self._get_sheet1_read_data()
        self._get_sheet2_read_data()
        self._get_preset_condition()


excel_read = ExcelRead()

